
package com.wulian.user.service.impl;

import com.baomidou.mybatisplus.mapper.EntityWrapper;
import com.baomidou.mybatisplus.service.impl.ServiceImpl;
import com.wulian.common.constants.CommonConstants;
import com.wulian.common.euums.EnumErrCode;
import com.wulian.common.exception.BusinessException;
import com.wulian.common.util.JSONUtil;
import com.wulian.common.vo.MenuVO;
import com.wulian.common.vo.UserVO;
import com.wulian.user.dto.DeptTree;
import com.wulian.user.dto.RoleDTO;
import com.wulian.user.dto.TreeNode;
import com.wulian.user.entity.*;
import com.wulian.user.mapper.*;
import com.wulian.user.service.SysDeptService;
import com.wulian.user.service.SysRoleMenuService;
import com.wulian.user.service.SysTreeService;
import com.wulian.user.util.TreeUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.cache.annotation.CacheEvict;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.util.*;
import java.util.stream.Collectors;

/**
 * <p>
 * 机构管理 服务实现类
 * </p>
 *
 * @author Administrator
 * @since 2018-01-20
 */
@Service
@Transactional
@Slf4j
public class SysDeptServiceImpl extends ServiceImpl<SysDeptMapper, SysDept> implements SysDeptService {
    @Autowired
    private SysDeptMapper sysDeptMapper;
    @Autowired
    private SysTreeService sysTreeService;
    @Autowired
    private SysRoleDeptMapper sysRoleDeptMapper;
    @Autowired
    private SysRoleMapper sysRoleMapper;
    @Autowired
    private SysRoleMenuService sysRoleMenuService;
    @Autowired
    private SysUserMapper sysUserMapper;
    @Autowired
    private SysMenuMapper sysMenuMapper;
    @Autowired
    private SysDictMapper sysDictMapper;


    public Map<String,Integer> add(SysDept  sysDept,Integer companyId) {
        Integer[] menuIdArr = null;
        EntityWrapper<SysDict> sysDictWrapper = new EntityWrapper<>();
        sysDictWrapper.eq("type","menuId");
        sysDictWrapper.and().eq("value","3");
        sysDictWrapper.and().eq("del_flag","0");
        sysDictWrapper.orderBy("sort");
        List<SysDict> sysDicts = sysDictMapper.selectList(sysDictWrapper);
        String[] split = null;
        if(null != sysDicts || 0 > sysDicts.size()){
            String label = sysDicts.get(0).getLabel();
            split = label.split(",");
        }
        EntityWrapper<SysMenu> sysMenuWrapper = new EntityWrapper<>();

        sysMenuWrapper.notIn("menu_id",split);
        sysMenuWrapper.and().eq("del_flag","0");
        List<SysMenu> sysMenus = sysMenuMapper.selectList(sysMenuWrapper);
        List<Integer> menuIdList = sysMenus.stream().map(e -> e.getMenuId()).collect(Collectors.toList());
        Integer[] menuIdArray = new Integer[menuIdList.size()];
        menuIdList.toArray(menuIdArray);
        return  insertDept2(sysDept,menuIdArray,companyId);
    }

    /*public Boolean add2(SysDept  sysDept) {
        Integer[] menuIdArr = null;
        EntityWrapper<SysDict> sysDictWrapper = new EntityWrapper<>();
        sysDictWrapper.eq("type","menuId");
        sysDictWrapper.and().eq("value","3");
        sysDictWrapper.and().eq("del_flag","0");
        sysDictWrapper.orderBy("sort");
        List<SysDict> sysDicts = sysDictMapper.selectList(sysDictWrapper);
        String[] split = null;
        if(null != sysDicts || 0 > sysDicts.size()){
            String label = sysDicts.get(0).getLabel();
            split = label.split(",");
        }
        EntityWrapper<SysMenu> sysMenuWrapper = new EntityWrapper<>();

        sysMenuWrapper.notIn("menu_id",split);
        sysMenuWrapper.and().eq("del_flag","0");
        List<SysMenu> sysMenus = sysMenuMapper.selectList(sysMenuWrapper);
        List<Integer> menuIdList = sysMenus.stream().map(e -> e.getMenuId()).collect(Collectors.toList());
        Integer[] menuIdArray = new Integer[menuIdList.size()];
        menuIdList.toArray(menuIdArray);
        return  insertDept(sysDept,menuIdArray);
    }*/

    /**
     * 添加信息机构
     *
     * @param dept 机构
     * @return
     */
    @Override
    public Boolean insertDept(SysDept dept,Integer[] menuIdArr,Integer CompanyId) {
        SysDept sysDept = new SysDept();
        BeanUtils.copyProperties(dept, sysDept);
        sysDept.setCompanyId(CompanyId);
        Integer i = sysDeptMapper.insertSysDept(sysDept);
        SysTree sysTree = new SysTree();
        sysTree.setTypeId( 2 );
        sysTree.setChriledId( Long.parseLong( sysDept.getDeptId().toString() ) );
        sysTree.setParentId( Long.parseLong( sysDept.getParentId().toString() ) );
        sysTree.setName( sysDept.getName() );
        sysTreeService.insertSysTree( sysTree );
        /**
         * 默认添加角色 start 方便拿到角色ID
         */
        RoleDTO roleDto = new RoleDTO();
        //默认生成角色编码规则
        roleDto.setRoleCode(String.valueOf(new Date().getTime()));
        roleDto.setRoleName(sysDept.getName());
        roleDto.setRoleDesc(sysDept.getName());
        roleDto.setRoleDeptId(sysDept.getDeptId());
        roleDto.setDelFlag(CommonConstants.DEL_FLAG_NO);
        //sysRoleService.insertRole(roleDto);
        SysRole sysRole = new SysRole();
        BeanUtils.copyProperties(roleDto, sysRole);
        sysRole.setIsAdmin("0");//管理员角色
        sysRole.setUpdateTime( new Date(  ) );
        sysRole.setCompanyId(CompanyId);
        sysRoleMapper.insert(sysRole);
        SysRoleDept roleDept = new SysRoleDept();
        roleDept.setRoleId(sysRole.getRoleId());
        roleDept.setDeptId(roleDto.getRoleDeptId());
        sysRoleDeptMapper.insert(roleDept);
        // 追加：RoleID返回值
        dept.setRoleId(sysRole.getRoleId());
        /**
         * 默认添加角色 end
         */
        
        /**
         * 默认添加当前用户的菜单权限 start
         */
        sysRoleMenuService.insertRoleMenus(sysRole.getRoleCode(), sysRole.getRoleId(), menuIdArr);
        
        /**
         * 默认添加当前用户的菜单权限 end
         */
        return Boolean.TRUE;
    }


    public Map<String,Integer> insertDept2(SysDept dept,Integer[] menuIdArr,Integer companyId) {
        SysDept sysDept = new SysDept();
        BeanUtils.copyProperties(dept, sysDept);
        Integer i = sysDeptMapper.insertSysDept(sysDept);
        SysTree sysTree = new SysTree();
        sysTree.setTypeId( 2 );
        sysTree.setChriledId( Long.parseLong( sysDept.getDeptId().toString() ) );
        sysTree.setParentId( Long.parseLong( sysDept.getParentId().toString() ) );
        sysTree.setName( sysDept.getName() );
        sysTreeService.insertSysTree( sysTree );
        /**
         * 默认添加角色 start 方便拿到角色ID
         */
        RoleDTO roleDto = new RoleDTO();
        //默认生成角色编码规则
        roleDto.setRoleCode(String.valueOf(new Date().getTime()));
        roleDto.setRoleName(sysDept.getName());
        roleDto.setRoleDesc(sysDept.getName());
        roleDto.setRoleDeptId(sysDept.getDeptId());
        roleDto.setDelFlag(CommonConstants.DEL_FLAG_NO);
        //sysRoleService.insertRole(roleDto);
        SysRole sysRole = new SysRole();
        BeanUtils.copyProperties(roleDto, sysRole);
        sysRole.setIsAdmin("0");//管理员角色
        sysRole.setUpdateTime( new Date(  ) );
        sysRole.setCompanyId(companyId);
        sysRoleMapper.insert(sysRole);
        SysRoleDept roleDept = new SysRoleDept();
        roleDept.setRoleId(sysRole.getRoleId());
        roleDept.setDeptId(roleDto.getRoleDeptId());
        sysRoleDeptMapper.insert(roleDept);
        /**
         * 默认添加角色 end
         */

        /**
         * 默认添加当前用户的菜单权限 start
         */
        sysRoleMenuService.insertRoleMenus(sysRole.getRoleCode(), sysRole.getRoleId(), menuIdArr);
        Map<String,Integer> map = new HashMap();
        map.put("deptId",sysDept.getDeptId());
        map.put("roleId",sysRole.getRoleId());
        return map;
    }
    /**
     * 删除机构
     *
     * @param id 机构 ID
     * @return 成功、失败
     */
    @Override
    @CacheEvict(value = "dept_info", key = "#id")
    public Boolean deleteDeptById(Integer id) {
        // 此处是真实删除，坑！
//        SysDept sysDept = new SysDept();
//        sysDept.setDeptId(id);
//        sysDept.setUpdateTime(new Date());
//        sysDept.setDelFlag(CommonConstants.STATUS_DEL);
//        return this.deleteById(sysDept);
        // 新增：软删除
        SysDept sysDept = new SysDept();
        sysDept.setDeptId(id);
        sysDept.setUpdateTime(new Date());
        sysDept.setDelFlag(CommonConstants.STATUS_DEL);
        sysDeptMapper.softdeleteById(sysDept);
        return true;
    }

    /**
     * 更新机构
     *
     * @param sysDept 机构信息
     * @return 成功、失败
     */
    @Override
    @CacheEvict(value = "dept_info", key = "#sysDept.deptId")
    public Boolean updateDeptById(SysDept sysDept) {
        if(sysDept.getDeptId()==0) {
            throw new BusinessException( EnumErrCode.PRDMC_CODE_1051 );
        }
        Map sysDeptMap = new HashMap<String,Object>(  );
        //更新机构状态
        sysDeptMap.put( "name",sysDept.getName() );
        sysDeptMap.put( "deptCode",sysDept.getDeptCode() );
        sysDeptMap.put( "deptId",sysDept.getDeptId());
        sysDeptMap.put( "updateTime",new Date(  ));
        sysDeptMap.put( "deptadminId", sysDept.getDeptadminId());
        sysDeptMap.put( "deptAddress", sysDept.getDeptAddress());
        // 20210513 追加经纬度
        sysDeptMap.put( "longitude", sysDept.getLatitude());
        sysDeptMap.put( "latitude", sysDept.getLongitude());
        sysDeptMapper.updatesysDeptById( sysDeptMap );
        Map map = new HashMap<String,Object>(  );
        map.put( "name",sysDept.getName() );
        map.put( "chriledId",sysDept.getDeptId() );
        sysDeptMapper.updateTree(map);
        //获取当前机构的管理员角色
        SysRole selectAdminRole = sysRoleMapper.selectAdminRoleByDeptId(sysDept.getDeptId());
        String menuIds = sysDept.getMenuIds();
    	if(null != selectAdminRole){
    		 Integer[] menuIdArr = null;
    	    	if(StringUtils.isNotBlank(menuIds)){
    	    		String[] menuIdArray = menuIds.split(",");
    	    		//将String数组转成Integer数组
    	    		menuIdArr = Arrays.stream(menuIdArray).map(Integer::valueOf).toArray(Integer[]::new);
    	    		sysRoleMenuService.insertRoleMenus(selectAdminRole.getRoleCode(), selectAdminRole.getRoleId(), menuIdArr);
    	    	}
    		 
    	}
        return true;
    }

    @Override
    @Cacheable(value = "dept_info", key = "#id")
    public SysDept selectSysDeptById(Integer id) {
    	SysDept sysDept = sysDeptMapper.selectSysDeptById( id );
    	//获取所选部门下管理员角色下的所有用户集合
    	String selectAdminRoleUsers = sysUserMapper.selectAdminRoleUsers(sysDept.getDeptId());
    	sysDept.setAdminRoleUsers(selectAdminRoleUsers);
    	SysRole selectAdminRole = sysRoleMapper.selectAdminRoleByDeptId(id);
    	if(null != selectAdminRole){
    		 List<MenuVO> menus = sysMenuMapper.findMenuByRoleName(selectAdminRole.getRoleCode());
    	        List<Integer> menuList = new ArrayList<>();
    	        for (MenuVO menuVo : menus) {
    	            menuList.add(menuVo.getMenuId());
    	        }
    	        sysDept.setMenuIdList(menuList);
    	}
        return sysDept;
    }


    @Override
    public Boolean checkCodeUnique(String deptCode) {
        Integer num = sysDeptMapper.checkCodeUnique(deptCode);
        if(num > 1){
            return false;
        }
        return true;
    }

    @Override
    public SysDept getSysDeptByDeptCode(String deptCode) {
        return sysDeptMapper.getSysDeptByDeptCode(deptCode);
    }

    @Override
    public List<SysDept> selectSysDeptList() {
        return sysDeptMapper.selectSysDeptList();
    }

    /**
     * 查询机构树
     *
     * @return 树
     */
    @Override
    public List<DeptTree> selectListTree(Integer deptId) {
        List<SysDept> depts= sysDeptMapper.selectSysDeptList();
        return getDeptTree(depts, deptId);
    }

    @Override
    public List<DeptTree> selectListTree_client(Map<String,Object> map, Integer deptId) {
        SysDept sysDept_root = sysDeptMapper.selectSysDeptById( deptId );
        List<SysDept> depts= sysDeptMapper.selectSysDeptClientList(map);
        // 防止root节点不被selectSysDeptClientList搜索到，导致返回结果错误
        // 故对getDeptadminId == null的dept进行补充追加
        if(sysDept_root.getDeptadminId() == null)
            depts.add(0, sysDept_root);
        return getDeptTree(depts, deptId);
    }

    /**
     * 构建机构树
     *
     * @param depts 机构
     * @param root  根节点
     * @return
     */
    private List<DeptTree> getDeptTree(List<SysDept> depts, int root) {
        List<DeptTree> trees = new ArrayList<>();
        DeptTree node;
        for (SysDept dept : depts) {
            if (dept.getParentId().equals(dept.getDeptId())) {
                continue;
            }
            node = new DeptTree();
            node.setId(dept.getDeptId());
            node.setParentId(dept.getParentId());
            node.setName(dept.getName());
            node.setParentName( dept.getParentName() );
            node.setDeptadminId(dept.getDeptadminId());
            node.setDeptAddress(dept.getDeptAddress());
            node.setDeptadminName(dept.getDeptadminName());
            node.setDeptadminStatus(dept.getDeptadminStatus());
            node.setDeptadminPhone(dept.getDeptadminPhone() );
            node.setDeptadminCreateTime(dept.getDeptadminCreateTime() );
            // 20210513 追加经纬度
            node.setLongitude(dept.getLongitude());
            node.setLatitude(dept.getLatitude());
            trees.add(node);
        }
        return TreeUtil.buildDept(trees, root);
    }

    @Override
    public Boolean updateObj(SysDept sysDept) {
        Map map = new HashMap<String,Object>(  );
        map.put( "deptId", sysDept.getDeptId());
        map.put( "retainComScale",sysDept.getRetainComScale() );
        sysDeptMapper.updateObj( map );
        return true;
    }

    @Override
    public List selectSysUserProjectTree(Integer deviceId,Integer userId) {
        // 获取项目信息
        //List<SysProjectDto> selectProjectList = getSysProjectList();
        // 根据用户id获取用户信息
        UserVO user = sysUserMapper.selectUserVoById(userId);
        log.info("根据用户id='" + userId + "'查询获取的用户信息 user:{}", JSONUtil.toJSON(user));

        List<DeptTree> selectListTree = selectListTreeByDeptId(deviceId,user.getDeptId()/*, selectProjectList*/);
        return selectListTree;
    }
    private List<DeptTree> selectListTreeByDeptId(Integer deviceId,int deptId/*,List<SysProjectDto> sysProjectDtoList*/) {
        List<SysDept> depts= sysDeptMapper.selectSysDeptList(  );
        return getDeptDataProjectTree(deviceId,depts, deptId/*,sysProjectDtoList*/);
    }
    /**
     * 构建机构树
     *
     * @param depts 机构
     * @param root  根节点
     * @return
     */
    private List<DeptTree> getDeptDataProjectTree(Integer deviceId,List<SysDept> depts, int root/*, List<SysProjectDto> sysProjectDtoList*/ ) {
        List<DeptTree> trees = new ArrayList<>();
        DeptTree node;
        for (SysDept dept : depts) {
            if (dept.getParentId().equals(dept.getDeptId())) {
                continue;
            }
            node = new DeptTree();
            node.setId(dept.getDeptId());
            node.setParentId(dept.getParentId());
            node.setName(dept.getName());
            node.setParentName(dept.getParentName());
            trees.add(node);
        }
        return build(deviceId,trees, root/*, sysProjectDtoList*/);
    }
    /**
     * 两层循环实现建树
     *
     * @param treeNodes 传入的树节点列表
     * @return
     */
    public <T extends TreeNode> List<T> build(Integer deviceId,List<T> treeNodes, Object root/*, List<SysProjectDto> sysProjectDtoList*/) {
        List<T> trees = new ArrayList<T>();
        //List<DeptProjectDto> projectList = projectList(deviceId,sysProjectDtoList);
        for (T treeNode : treeNodes) {
            if (root.equals(treeNode.getId())) {
                trees.add(treeNode);
            }

            for (T it : treeNodes) {
                if (it.getParentId() == treeNode.getId()) {
                    if (treeNode.getChildren() == null) {
                        treeNode.setChildren(new ArrayList<TreeNode>());
                    }
                    treeNode.add(it);
                }
            }

            // for循环绑定机构与项目的关系
            /*for (DeptProjectDto dpd : projectList) {
                if (String.valueOf(treeNode.getId()).equals(dpd.getOrgId())) {
                    treeNode.add(dpd);
                }

            }*/
        }
        return trees;
    }

}
